package com.siyoumi.sh.modules.gzhc365;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.siyoumi.sh.modules.common.HandleBase;
import com.siyoumi.sh.modules.common.send_msg.TlSendMsg;
import com.siyoumi.sh.modules.gzhc365.entity.GzhcApiToken;
import com.siyoumi.sh.modules.gzhc365.entity.GzhcDoctor;
import com.siyoumi.sh.modules.gzhc365.entity.GzhcDoctorWorkTime;
import com.siyoumi.sh.modules.gzhc365.entity.GzhcDoctorWorkToday;
import com.siyoumi.util.*;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

//建行ccb
@Slf4j
public class GzhcHandleBase
        extends HandleBase {
    @Getter
    String userAgent = "Mozilla/5.0 (Linux; Android 8.0.0; FRD-AL00 Build/HUAWEIFRD-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/107.0.5304.141 Mobile Safari/537.36 XWEB/5127 MMWEBSDK/20230504 MMWEBID/2103 MicroMessenger/8.0.37.2380(0x2800255B) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android";

    protected Map<String, String> getHeader() {
        Map<String, String> mapHeader = new HashMap<>();
        mapHeader.put("User-Agent", getUserAgent());
        return mapHeader;
    }

    /**
     * token格式
     * login_access_token|name@login_access_toke2|name2
     */
    protected List<GzhcApiToken> getArrToken() {
        String token = System.getenv("GZHC_TOKEN");
        if (XStr.isNullOrEmpty(token)) {
            return new ArrayList<>();
        }

        List<GzhcApiToken> tokenList = new ArrayList<>();
        String[] tokenArr = token.split("@");
        for (String s : tokenArr) {
            String[] dataArr = s.split("\\|");

            tokenList.add(GzhcApiToken.getIns(dataArr[0], dataArr[1]));
        }

        return tokenList;
    }


    protected XReturn paresR(String returnStr) {
        XReturn r = XReturn.parse(returnStr);
        String message = r.getData("message");
        Object code = r.getData("code");
        Integer codeNum = 123456;
        if (code instanceof String) {
            codeNum = XStr.toInt((String) code);
        }
        if (code instanceof Integer) {
            codeNum = (Integer) code;
        }

        r.setErrMsg(message);
        r.setErrCode(codeNum);

        return r;
    }


    public XReturn forPostForm(String url, Map<String, String> header, Map<String, String> postData) {
        XReturn r;
        while (true) {
            try {
                r = postForm(url, header, postData);
                Object data = r.getData("data");
                if (r.ok() && data == null) {
                    log.info("接口数据异常data == null");
                    continue;
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                if (ex.getMessage().contains("timed out")) {
                    //超时重试
                    log.info("接口超时重试");
                    XApp.sleepMs(200);
                    continue;
                }
                if (ex.getMessage().contains("502")
                        || ex.getMessage().contains("500")) {
                    //网关错误
                    log.info("接口500或者502重试");
                    XApp.sleepMs(1000);
                    continue;
                }

                r = XReturn.getR(123456, ex.getMessage());
            }

            break;
        }

        return r;
    }

    public XReturn postForm(String url, Map<String, String> header, Map<String, String> postData) {
        log.debug("url: {}", url);
        log.debug("post_data: {}", XJson.toJSONString(postData));

        XHttpClient client = XHttpClient.getInstance(3000);

        String returnStr = client.postForm(url, header, postData);
        log.debug("return_str: {}", returnStr);
        return paresR(returnStr);
    }

    /**
     * 抢
     *
     * @param apiToken
     * @param doctor
     * @param doctorWorkMax
     */
    public void qiang(GzhcApiToken apiToken, GzhcDoctor doctor, GzhcDoctorWorkToday doctorWorkMax) {
        Boolean sort = doctorWorkMax.getTimeType() != 1;

        List<GzhcDoctorWorkTime> listTime = new ArrayList<>();
        while (true) {
            listTime = getDoctorDay(apiToken, doctor, doctorWorkMax, sort);
            if (listTime.size() <= 0) {
                logAndSet(TlSendMsg.get(), "挂号时间为空，重新获取\n\n");
                XApp.sleepMs(1000);
                continue;
            }

            break;
        }

        for (GzhcDoctorWorkTime item : listTime) {
            logAndSet(TlSendMsg.get(), XStr.format("{0}-{1}:￥{2}[{3}],库:{4}\n\n", item.getVisitBeginTime(), item.getVisitEndTime()
                            , (item.getRegisterFee() / 100) + ""
                            , item.getVisitQueue()
                            , item.getLeftSource().toString()
                    )
            );
        }

        if (!doctor.getTest()) {
            for (GzhcDoctorWorkTime time : listTime) {
                logAndSet(TlSendMsg.get(), XStr.format("{0}-{1}准备抢\n\n", time.getVisitBeginTime(), time.getVisitEndTime()));
                //订单确认
                {
                    XReturn r = registerConfirm(apiToken, doctor, doctorWorkMax, time);
                    if (r.err()) {
                        break;
                    }
                }

                if (!doctor.getTest()) {
                    //下单
                    XReturn r = order(apiToken, doctor, doctorWorkMax, time);
                    if (r.ok()) {
                        //成功跳出，失败去预约下个时间段
                        logAndSet(TlSendMsg.get(), XStr.format("抢到了\n\n"));
                        break;
                    } else {
                        logAndSet(TlSendMsg.get(), XStr.format("没抢到，跳过\n\n"));
                    }
                }
            }
        }
    }

    public List<GzhcDoctorWorkTime> getDoctorDay(GzhcApiToken apiToken, GzhcDoctor doctor, GzhcDoctorWorkToday work) {
        return getDoctorDay(apiToken, doctor, work, true);
    }

    /**
     * 获取医生某天挂号详情
     *
     * @param apiToken
     * @param doctor
     * @param work
     * @param sort     true：顺序；false：倒序
     */
    public List<GzhcDoctorWorkTime> getDoctorDay(GzhcApiToken apiToken, GzhcDoctor doctor, GzhcDoctorWorkToday work, Boolean sort) {
        String url = "https://mix.med.gzhc365.com/api/register/schedulelist";

        Map<String, String> postData = new HashMap<>();
        postData.put("hisId", doctor.getHisId());
        postData.put("subHisId", doctor.getSubHisId());
        postData.put("platformId", doctor.getPlatformId());
        postData.put("platformSource", doctor.getPlatformSource());
        postData.put("subSource", doctor.getSubSource());
        postData.put("doctorId", doctor.getId());
        postData.put("deptId", work.getDeptNo());
        postData.put("scheduleDate", XDate.toDateString(work.getDate()));

        postData.put("login_access_token", apiToken.getToken());

        XReturn r = forPostForm(url, getHeader(), postData);
        if (r.err()) {
            logAndSet(TlSendMsg.get(), "获取医生某天挂号详情失败：" + r.getErrMsg() + "\n\n");
            return null;
        }

        LinkedList<GzhcDoctorWorkTime> listData = new LinkedList<>();

        JSONObject data = (JSONObject) r.get("data");
        JSONArray itemList = (JSONArray) data.getJSONArray("itemList");
        for (Object item : itemList) {
            JSONObject obj = (JSONObject) item;

            GzhcDoctorWorkTime doctorWork = XJson.parseObject(obj.toJSONString(), GzhcDoctorWorkTime.class);
            if (doctorWork.getLeftSource() <= 0) {
                //LeftSource小于等下0表示约满
                if (!doctor.getTest()) {
                    continue;
                }
            }


            if (sort) {
                //时间顺序
                listData.add(doctorWork);
            } else {
                //时间倒序
                listData.addFirst(doctorWork);
            }
        }

        return listData;
    }

    //订单确认、拿用户ID
    public XReturn registerConfirm(GzhcApiToken apiToken, GzhcDoctor doctor, GzhcDoctorWorkToday work, GzhcDoctorWorkTime time) {
        String url = "https://mix.med.gzhc365.com/api/register/registerconfirm";

        Map<String, String> postData = new HashMap<>();
        postData.put("hisId", doctor.getHisId());
        postData.put("subHisId", doctor.getSubHisId());
        postData.put("platformId", doctor.getPlatformId());
        postData.put("platformSource", doctor.getPlatformSource());
        postData.put("subSource", doctor.getSubSource());
        postData.put("doctorId", doctor.getId());
        postData.put("deptId", work.getDeptNo());
        postData.put("scheduleDate", XDate.toDateString(work.getDate()));
        postData.put("scheduleId", time.getScheduleId());
        postData.put("visitPeriod", time.getVisitPeriod().toString());
        postData.put("visitBeginTime", time.getVisitBeginTime());
        postData.put("visitEndTime", time.getVisitEndTime());

        postData.put("login_access_token", apiToken.getToken());

        XReturn r = forPostForm(url, getHeader(), postData);
        if (r.err()) {
            logAndSet(TlSendMsg.get(), "订单确认失败：" + r.getErrMsg() + "\n\n");
            return r;
        }

        List<GzhcDoctorWorkTime> listData = new ArrayList<>();

        JSONObject data = (JSONObject) r.get("data");
        JSONArray patientList = (JSONArray) data.getJSONArray("patientList");
        for (Object item : patientList) {
            JSONObject obj = (JSONObject) item;

            String patientId = obj.getString("patientId");
            apiToken.setPatientId(patientId);
            break;
        }

        return r;
    }

    //下单
    public XReturn order(GzhcApiToken apiToken, GzhcDoctor doctor, GzhcDoctorWorkToday work, GzhcDoctorWorkTime time) {
        String url = "https://mix.med.gzhc365.com/api/register/generatororder";

        Map<String, String> postData = new HashMap<>();
        postData.put("hisId", doctor.getHisId());
        postData.put("subHisId", doctor.getSubHisId());
        postData.put("platformId", doctor.getPlatformId());
        postData.put("platformSource", doctor.getPlatformSource());
        postData.put("subSource", doctor.getSubSource());
        postData.put("doctorId", doctor.getId());
        postData.put("deptId", work.getDeptNo());
        postData.put("scheduleDate", XDate.toDateString(work.getDate()));
        postData.put("scheduleId", time.getScheduleId());
        postData.put("visitPeriod", time.getVisitPeriod().toString());
        postData.put("visitBeginTime", time.getVisitBeginTime());
        postData.put("visitEndTime", time.getVisitEndTime());
        postData.put("outExtFieldsFlag", "1");
        postData.put("extFields", time.getExtFields());
        postData.put("patientId", apiToken.getPatientId());
        postData.put("payFlag", "1");
        postData.put("transParam", "{\"regType\":\"1\"}");
        postData.put("medicalFlag", "0");

        postData.put("login_access_token", apiToken.getToken());

        XReturn r = forPostForm(url, getHeader(), postData);
        if (r.err()) {
            logAndSet(TlSendMsg.get(), "下单失败：" + r.getErrMsg() + "\n\n");
            return r;
        }

        return r;
    }
}
